package cn.edu.zafu.bigdata.YinMingyan.chapter10;

public class SynchronizedDemo {
    public static void main(String[] args) throws Exception{
        //var 是一个类型推断关键词，它允许编译器根据赋值的右侧来推断变量的类型
        //1.AddThread和DEcThread都是Thread的子类，使用var可以提高代码的简洁性
        //2.强调AddThread和DEcThread类的行为（即它们是线程）而不是它们的具体类型
        var add = new AddThread();
        var dec = new DecThread();
        add.start();
        dec.start();
        add.join();
        dec.join();
        System.out.println(Counter.count);
    }
}


class Counter{
    public static final Object lock = new Object();
    //错误示例
    // public static final Object lock1 = new Object();
    // public static final Object lock2 = new Object();
    public static int count = 0;
}

class AddThread extends Thread{
    public void run(){
        for (int i = 0; i < 10000; i++) {
            //使用synchronized的时候，不必担心抛出异常。因为无论是否有异常，都会在synchronized结束处正确释放锁
            synchronized (Counter.lock){ //获取锁
                Counter.count += 1;
            } //释放锁
            /*
            synchronized (Counter.lock1){ //获取锁
                Counter.count += 1;
            }
             */
        }
    }
}

class DecThread extends Thread{
    public void run(){
        for (int i = 0; i < 10000; i++) {
            synchronized (Counter.lock) {
                Counter.count -= 1;
            }
            /*
            synchronized (Counter.lock2){ //获取锁
                Counter.count += 1;
            }
            结果并不是0，这是因为两个线程各自的synchronized锁住的不是同一个对象！
            这使得两个线程各自都可以同时获得锁：因为JVM只保证同一个锁在任意时刻只能被一个线程获取，
            但两个不同的锁在同一时刻可以被两个线程分别获取
             */
        }
    }

}